{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {},
  "cells": [
    {
      "metadata": {},
      "source": [
        "<td>\n",
        "   <a target=\"_blank\" href=\"https://labelbox.com\" ><img src=\"https://labelbox.com/blog/content/images/2021/02/logo-v4.svg\" width=256/></a>\n",
        "</td>"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "<td>\n",
        "<a href=\"https://colab.research.google.com/github/Labelbox/labelbox-python/blob/master/examples/prediction_upload/geospatial_predictions.ipynb\" target=\"_blank\"><img\n",
        "src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"></a>\n",
        "</td>\n",
        "\n",
        "<td>\n",
        "<a href=\"https://github.com/Labelbox/labelbox-python/blob/master/examples/prediction_upload/geospatial_predictions.ipynb\" target=\"_blank\"><img\n",
        "src=\"https://img.shields.io/badge/GitHub-100000?logo=github&logoColor=white\" alt=\"GitHub\"></a>\n",
        "</td>"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "# Geospatial Prediction Import \n",
        "* This notebook walks you through the process of uploading model predictions to a Model Run. This notebook provides an example for each supported prediction type for tiled imagery assets.\n",
        "\n",
        "A Model Run is a container for the predictions, annotations and metrics of a specific experiment in your ML model development cycle.\n",
        "\n",
        "**Supported annotations that can be uploaded through the SDK**\n",
        "- Bounding box\n",
        "- Point\n",
        "- Polygons \n",
        "- Polyline\n",
        "- Free form text classifications\n",
        "- Classification - radio\n",
        "- Classification - checklist\n",
        "\n",
        "**NOT** supported:\n",
        "- Segmentation masks\n",
        "\n",
        "\n",
        "Please note that this list of unsupported annotations only refers to limitations for importing annotations. For example, when using the Labelbox editor, segmentation masks can be created and edited on video assets.\n"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "## Setup"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "!pip install -q 'labelbox[data]'"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "import os\n",
        "\n",
        "import uuid\n",
        "import numpy as np\n",
        "from PIL import Image\n",
        "import cv2\n",
        "\n",
        "import labelbox as lb\n",
        "import labelbox.types as lb_types"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "## Replace with your API Key \n",
        "Guides on [Create an API key](https://docs.labelbox.com/docs/create-an-api-key)"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "API_KEY = \"\"\n",
        "client = lb.Client(API_KEY)"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "## Supported Predictions\n",
        "- Each cell shows the python annotation and the NDJson annotation for each annotation type."
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "\n",
        "####### Point #######\n",
        "\n",
        "# Python Annotation\n",
        "point_prediction = lb_types.ObjectAnnotation(\n",
        "  name = \"point_geo\",\n",
        "  confidence=0.4,\n",
        "  value = lb_types.Point(x=-99.20647859573366, y=19.40018029091072),\n",
        ")\n",
        "\n",
        "# NDJSON\n",
        "point_prediction_ndjson = {\n",
        "    \"name\": \"point_geo\",\n",
        "    \"confidence\": 0.4,\n",
        "    \"point\": {\n",
        "         \"x\": -99.20647859573366,\n",
        "         \"y\": 19.40018029091072\n",
        "     }\n",
        "}"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "\n",
        "####### Polyline #######\n",
        "# Coordinates\n",
        "coords = [\n",
        "            [\n",
        "                -99.20842051506044,\n",
        "                19.40032196622975\n",
        "            ],\n",
        "            [\n",
        "                -99.20809864997865,\n",
        "                19.39758963475322\n",
        "            ],\n",
        "            [\n",
        "                -99.20758366584778,\n",
        "                19.39776167179227\n",
        "            ],\n",
        "            [\n",
        "                -99.20728325843811,\n",
        "                19.3973265189299\n",
        "            ]\n",
        "        ]\n",
        "\n",
        "line_points = []\n",
        "line_points_ndjson = []\n",
        "\n",
        "for sub in coords: \n",
        "  line_points.append(lb_types.Point(x=sub[0], y=sub[1]))\n",
        "  line_points_ndjson.append({\"x\":sub[0], \"y\":sub[1]})\n",
        "\n",
        "# Python Annotation \n",
        "polyline_prediction = lb_types.ObjectAnnotation(\n",
        "  name = \"polyline_geo\",\n",
        "  confidence=0.5,\n",
        "  value = lb_types.Line(points=line_points),\n",
        ")\n",
        "\n",
        "# NDJSON \n",
        "polyline_prediction_ndjson = {\n",
        "    \"name\": \"polyline_geo\",\n",
        "    \"confidence\": 0.5,\n",
        "    \"line\": line_points_ndjson\n",
        "}"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "\n",
        "####### Polygon #######\n",
        "# Coordinates in the desired EPSG coordinate system\n",
        "coords_polygon = [\n",
        "    [\n",
        "        -99.21042680740356,\n",
        "        19.40036244486966\n",
        "    ],\n",
        "    [\n",
        "        -99.2104160785675,\n",
        "        19.40017017124035\n",
        "    ],\n",
        "    [\n",
        "        -99.2103409767151,\n",
        "        19.400008256428897\n",
        "    ],\n",
        "    [\n",
        "        -99.21014785766603,\n",
        "        19.400008256428897\n",
        "    ],\n",
        "    [\n",
        "        -99.21019077301027,\n",
        "        19.39983622176518\n",
        "    ],\n",
        "    [\n",
        "        -99.21022295951845,\n",
        "        19.399674306621385\n",
        "    ],\n",
        "    [\n",
        "        -99.21029806137086,\n",
        "        19.39951239131646\n",
        "    ],\n",
        "    [\n",
        "        -99.2102873325348,\n",
        "        19.399340356128437\n",
        "    ],\n",
        "    [\n",
        "        -99.21025514602663,\n",
        "        19.399117722085677\n",
        "    ],\n",
        "    [\n",
        "        -99.21024441719057,\n",
        "        19.39892544698541\n",
        "    ],\n",
        "    [\n",
        "        -99.2102336883545,\n",
        "        19.39874329141769\n",
        "    ],\n",
        "    [\n",
        "        -99.21021223068239,\n",
        "        19.398561135646027\n",
        "    ],\n",
        "    [\n",
        "        -99.21018004417421,\n",
        "        19.398399219233365\n",
        "    ],\n",
        "    [\n",
        "        -99.21011567115785,\n",
        "        19.39822718286836\n",
        "    ],\n",
        "    [\n",
        "        -99.20992255210878,\n",
        "        19.398136104719125\n",
        "    ],\n",
        "    [\n",
        "        -99.20974016189577,\n",
        "        19.398085505725305\n",
        "    ],\n",
        "    [\n",
        "        -99.20957922935487,\n",
        "        19.398004547302467\n",
        "    ],\n",
        "    [\n",
        "        -99.20939683914186,\n",
        "        19.39792358883935\n",
        "    ],\n",
        "    [\n",
        "        -99.20918226242067,\n",
        "        19.39786286996558\n",
        "    ],\n",
        "    [\n",
        "        -99.20899987220764,\n",
        "        19.397822390703805\n",
        "    ],\n",
        "    [\n",
        "        -99.20891404151918,\n",
        "        19.397994427496787\n",
        "    ],\n",
        "    [\n",
        "        -99.20890331268312,\n",
        "        19.398176583902874\n",
        "    ],\n",
        "    [\n",
        "        -99.20889258384706,\n",
        "        19.398368859888045\n",
        "    ],\n",
        "    [\n",
        "        -99.20889258384706,\n",
        "        19.398540896103246\n",
        "    ],\n",
        "    [\n",
        "        -99.20890331268312,\n",
        "        19.39872305189756\n",
        "    ],\n",
        "    [\n",
        "        -99.20889258384706,\n",
        "        19.39890520748796\n",
        "    ],\n",
        "    [\n",
        "        -99.20889258384706,\n",
        "        19.39907724313608\n",
        "    ],\n",
        "    [\n",
        "        -99.20889258384706,\n",
        "        19.399259398329956\n",
        "    ],\n",
        "    [\n",
        "        -99.20890331268312,\n",
        "        19.399431433603585\n",
        "    ],\n",
        "    [\n",
        "        -99.20890331268312,\n",
        "        19.39961358840092\n",
        "    ],\n",
        "    [\n",
        "        -99.20890331268312,\n",
        "        19.399785623300048\n",
        "    ],\n",
        "    [\n",
        "        -99.20897841453552,\n",
        "        19.399937418648214\n",
        "    ],\n",
        "    [\n",
        "        -99.20919299125673,\n",
        "        19.399937418648214\n",
        "    ],\n",
        "    [\n",
        "        -99.2093861103058,\n",
        "        19.39991717927664\n",
        "    ],\n",
        "    [\n",
        "        -99.20956850051881,\n",
        "        19.39996777770086\n",
        "    ],\n",
        "    [\n",
        "        -99.20961141586305,\n",
        "        19.40013981222548\n",
        "    ],\n",
        "    [\n",
        "        -99.20963287353517,\n",
        "        19.40032196622975\n",
        "    ],\n",
        "    [\n",
        "        -99.20978307724,\n",
        "        19.4004130431554\n",
        "    ],\n",
        "    [\n",
        "        -99.20996546745302,\n",
        "        19.40039280384301\n",
        "    ],\n",
        "    [\n",
        "        -99.21019077301027,\n",
        "        19.400372564528084\n",
        "    ],\n",
        "    [\n",
        "        -99.21042680740356,\n",
        "        19.40036244486966\n",
        "    ]\n",
        "    \n",
        "]\n",
        "\n",
        "polygon_points = []\n",
        "polygon_points_ndjson = []\n",
        "\n",
        "for sub in coords_polygon: \n",
        "  polygon_points.append(lb_types.Point(x=sub[0], y=sub[1]))\n",
        "  polygon_points_ndjson.append({\"x\":sub[0], \"y\":sub[1]})\n",
        "\n",
        "# Python Annotation \n",
        "polygon_prediction = lb_types.ObjectAnnotation(\n",
        "  name = \"polygon_geo\",\n",
        "  confidence=0.5,\n",
        "  value = lb_types.Polygon(points=polygon_points),\n",
        ")\n",
        "\n",
        "# NDJSON \n",
        "polygon_prediction_ndjson = {\n",
        "    \"name\": \"polygon_geo\",\n",
        "    \"confidence\": 0.5,\n",
        "    \"polygon\": polygon_points_ndjson\n",
        "}"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "\n",
        "####### Bounding Box #######\n",
        "coord_object =  {\n",
        "    \"coordinates\" : [[\n",
        "            [\n",
        "                -99.20746564865112,\n",
        "                19.39799442829336\n",
        "            ],\n",
        "            [\n",
        "                -99.20746564865112,\n",
        "                19.39925939999194\n",
        "            ],\n",
        "            [\n",
        "                -99.20568466186523,\n",
        "                19.39925939999194\n",
        "            ],\n",
        "            [\n",
        "                -99.20568466186523,\n",
        "                19.39799442829336\n",
        "            ],\n",
        "            [\n",
        "                -99.20746564865112,\n",
        "                19.39799442829336\n",
        "            ]\n",
        "        ]]\n",
        "}\n",
        "      \n",
        "\n",
        "\n",
        "\n",
        "bbox_top_left = lb_types.Point(x= -99.20746564865112, y=19.39799442829336)\n",
        "bbox_bottom_right = lb_types.Point(x=-99.20568466186523, y=19.39925939999194)\n",
        "\n",
        "# Python Annotation\n",
        "bbox_prediction = lb_types.ObjectAnnotation(\n",
        "  name = \"bbox_geo\",\n",
        "  confidence=0.5,\n",
        "  value = lb_types.Rectangle(start=bbox_top_left, end=bbox_bottom_right)\n",
        ")\n",
        "\n",
        "\n",
        "# NDJSON\n",
        "bbox_prediction_ndjson = {\n",
        "    \"name\" : \"bbox_geo\",\n",
        "    \"confidence\": 0.5,\n",
        "    \"bbox\" : {\n",
        "        'top': coord_object[\"coordinates\"][0][1][1],\n",
        "        'left': coord_object[\"coordinates\"][0][1][0],\n",
        "        'height': coord_object[\"coordinates\"][0][3][1] - coord_object[\"coordinates\"][0][1][1],        \n",
        "        'width': coord_object[\"coordinates\"][0][3][0] - coord_object[\"coordinates\"][0][1][0]\n",
        "    }\n",
        "}\n"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "\n",
        "####### Classification - radio (single choice) #######\n",
        "\n",
        "# Python Annotation \n",
        "radio_prediction = lb_types.ClassificationAnnotation(\n",
        "    name=\"radio_question_geo\", \n",
        "    value=lb_types.Radio(answer=lb_types.ClassificationAnswer(name=\"first_radio_answer\", confidence=0.5))\n",
        ")\n",
        "\n",
        "\n",
        "# NDJSON \n",
        "radio_prediction_ndjson = {\n",
        "    \"name\": \"radio_question_geo\",\n",
        "    \"answer\": { \"name\": \"first_radio_answer\", \"confidence\": 0.5}\n",
        "}"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "####### Classification - Checklist (multi-choice) #######\n",
        "\n",
        "coord_object_checklist = {\n",
        "    \"coordinates\": [\n",
        "       [\n",
        "            [\n",
        "                -99.210266,\n",
        "                19.39540372195134\n",
        "            ],\n",
        "            [\n",
        "                -99.210266,\n",
        "                19.396901\n",
        "            ],\n",
        "            [\n",
        "                -99.20621067903966,\n",
        "                19.396901\n",
        "            ],\n",
        "            [\n",
        "                -99.20621067903966,\n",
        "                19.39540372195134\n",
        "            ],\n",
        "            [\n",
        "                -99.210266,\n",
        "                19.39540372195134\n",
        "            ]\n",
        "      ]\n",
        "    ]          \n",
        "}\n",
        "\n",
        "# Python Annotation\n",
        "bbox_with_checklist_subclass = lb_types.ObjectAnnotation(\n",
        "    name=\"bbox_checklist_geo\",\n",
        "    confidence=0.5,\n",
        "    value=lb_types.Rectangle(\n",
        "        start=lb_types.Point(x=-99.210266, y=19.39540372195134), # Top left\n",
        "        end=lb_types.Point(x=-99.20621067903966, y=19.396901), # Bottom right\n",
        "    ),\n",
        "    classifications=[\n",
        "        lb_types.ClassificationAnnotation(\n",
        "            name=\"checklist_class_name\",\n",
        "            value=lb_types.Checklist(\n",
        "                answer=[lb_types.ClassificationAnswer(name=\"first_checklist_answer\", confidence=0.5)]\n",
        "            )\n",
        "        )\n",
        "    ]\n",
        ")\n",
        "\n",
        "\n",
        "# NDJSON \n",
        "bbox_with_checklist_subclass_ndjson = {\n",
        "    \"name\": \"bbox_checklist_geo\", \n",
        "    \"confidence\": 0.5,\n",
        "    \"classifications\": [{\n",
        "        \"name\": \"checklist_class_name\",\n",
        "        \"answer\": [\n",
        "            { \"name\":\"first_checklist_answer\", \"confidence\": 0.5}\n",
        "        ]   \n",
        "    }],\n",
        "    \"bbox\": {\n",
        "        'top': coord_object_checklist[\"coordinates\"][0][1][1],\n",
        "        'left': coord_object_checklist[\"coordinates\"][0][1][0],\n",
        "        'height': coord_object_checklist[\"coordinates\"][0][3][1] - coord_object_checklist[\"coordinates\"][0][1][1],        \n",
        "        'width': coord_object_checklist[\"coordinates\"][0][3][0] - coord_object_checklist[\"coordinates\"][0][1][0]\n",
        "    }\n",
        "}"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "####### Classification free form text with bbox #######\n",
        "\n",
        "coord_object_text ={\n",
        "    \"coordinates\": [\n",
        "      [\n",
        "        [\n",
        "            -99.21019613742828,\n",
        "            19.397447957052933\n",
        "        ],\n",
        "        [\n",
        "            -99.21019613742828,\n",
        "            19.39772119262215\n",
        "        ],\n",
        "        [\n",
        "            -99.20986354351044,\n",
        "            19.39772119262215\n",
        "        ],\n",
        "        [\n",
        "            -99.20986354351044,\n",
        "            19.397447957052933\n",
        "        ],\n",
        "        [\n",
        "            -99.21019613742828,\n",
        "            19.397447957052933\n",
        "        ]\n",
        "      ]\n",
        "    ]\n",
        "}\n",
        "# Python Annotation\n",
        "bbox_with_free_text_subclass = lb_types.ObjectAnnotation(\n",
        "    name=\"bbox_text_geo\",\n",
        "    value=lb_types.Rectangle(\n",
        "        start=lb_types.Point(x=-99.21019613742828, y=19.397447957052933), # Top left\n",
        "        end=lb_types.Point(x=-99.20986354351044, y=19.39772119262215), # Bottom right\n",
        "    ),\n",
        "    classifications=[\n",
        "        lb_types.ClassificationAnnotation(\n",
        "            name=\"free_text_geo\",\n",
        "            value=lb_types.Text(answer=\"sample text\")\n",
        "        )\n",
        "    ]\n",
        ")\n",
        "\n",
        "# NDJSON \n",
        "bbox_with_free_text_subclass_ndjson = {\n",
        "    \"name\":\"bbox_text_geo\",\n",
        "    \"confidence\": 0.5,\n",
        "    \"classifications\": [{\n",
        "        \"name\": \"free_text_geo\",\n",
        "        \"confidence\": 0.5,\n",
        "        \"answer\": \"sample text\"\n",
        "    }],\n",
        "    \"bbox\": {\n",
        "        'top': coord_object_text[\"coordinates\"][0][1][1],\n",
        "        'left': coord_object_text[\"coordinates\"][0][1][0],\n",
        "        'height': coord_object_text[\"coordinates\"][0][3][1] - coord_object_text[\"coordinates\"][0][1][1],        \n",
        "        'width': coord_object_text[\"coordinates\"][0][3][0] - coord_object_text[\"coordinates\"][0][1][0]\n",
        "    }\n",
        "}"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "####### Classification - Checklist (multi-choice) #######\n",
        "\n",
        "# Python Annotation\n",
        "checklist_prediction = lb_types.ClassificationAnnotation(\n",
        "    name=\"checklist_question_geo\",\n",
        "    value=lb_types.Checklist(answer = [\n",
        "        lb_types.ClassificationAnswer(name = \"first_checklist_answer\", confidence = 0.5),\n",
        "        lb_types.ClassificationAnswer(name = \"second_checklist_answer\", confidence = 0.5),\n",
        "        lb_types.ClassificationAnswer(name = \"third_checklist_answer\", confidence = 0.5)\n",
        "    ])\n",
        "  )\n",
        "\n",
        "\n",
        "# NDJSON\n",
        "checklist_prediction_ndjson = {\n",
        "  'name': 'checklist_question_geo',\n",
        "  'answer': [\n",
        "    {'name': 'first_checklist_answer', \"confidence\": 0.5},\n",
        "    {'name': 'second_checklist_answer', \"confidence\": 0.5},\n",
        "    {'name': 'third_checklist_answer', \"confidence\": 0.5},\n",
        "  ]\n",
        "}"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "\n",
        "########## Classification - Radio and Checklist (with subclassifications)  ##########\n",
        "\n",
        "nested_radio_prediction = lb_types.ClassificationAnnotation(\n",
        "  name=\"nested_radio_question\",\n",
        "  value=lb_types.Radio(\n",
        "    answer=lb_types.ClassificationAnswer(\n",
        "      name=\"first_radio_answer\",\n",
        "      confidence=0.5,\n",
        "      classifications=[\n",
        "        lb_types.ClassificationAnnotation(\n",
        "          name=\"sub_radio_question\",\n",
        "          value=lb_types.Radio(\n",
        "            answer=lb_types.ClassificationAnswer(\n",
        "              name=\"first_sub_radio_answer\",\n",
        "              confidence=0.2\n",
        "            )\n",
        "          )\n",
        "        )\n",
        "      ]\n",
        "    )\n",
        "  )\n",
        ")\n",
        "# NDJSON\n",
        "nested_radio_prediction_ndjson= {\n",
        "  \"name\": \"nested_radio_question\",\n",
        "  \"answer\": {\n",
        "      \"name\": \"first_radio_answer\",\n",
        "      \"confidence\": 0.2,\n",
        "      \"classifications\": [{\n",
        "          \"name\":\"sub_radio_question\",\n",
        "          \"answer\": { \"name\" : \"first_sub_radio_answer\", \"confidence\": 0.3}\n",
        "        }]\n",
        "    }\n",
        "}\n",
        "\n",
        "nested_checklist_prediction = lb_types.ClassificationAnnotation(\n",
        "  name=\"nested_checklist_question\",\n",
        "  value=lb_types.Checklist(\n",
        "    answer=[lb_types.ClassificationAnswer(\n",
        "      name=\"first_checklist_answer\",\n",
        "      confidence=0.5,\n",
        "      classifications=[\n",
        "        lb_types.ClassificationAnnotation(\n",
        "          name=\"sub_checklist_question\",\n",
        "          value=lb_types.Checklist(\n",
        "            answer=[lb_types.ClassificationAnswer(\n",
        "            name=\"first_sub_checklist_answer\", \n",
        "            confidence=0.5\n",
        "          )]\n",
        "        ))\n",
        "      ]\n",
        "    )]\n",
        "  )\n",
        ")\n",
        "nested_checklist_prediction_ndjson = {\n",
        "  \"name\": \"nested_checklist_question\",\n",
        "  \"answer\": [{\n",
        "      \"name\": \"first_checklist_answer\", \n",
        "      \"confidence\":0.5,\n",
        "      \"classifications\" : [\n",
        "        {\n",
        "          \"name\": \"sub_checklist_question\", \n",
        "          \"answer\": {\"name\": \"first_sub_checklist_answer\", \"confidence\": 0.5}\n",
        "        }          \n",
        "      ]         \n",
        "  }]\n",
        "}"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "## Step 1: Import data rows into Catalog"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "\n",
        "top_left_bound = lb_types.Point(x=-99.21052827588443, y=19.400498983095076)\n",
        "bottom_right_bound = lb_types.Point(x=-99.20534818927473, y=19.39533555271248)\n",
        "\n",
        "epsg = lb_types.EPSG.EPSG4326\n",
        "bounds = lb_types.TiledBounds(epsg=epsg, bounds=[top_left_bound, bottom_right_bound])\n",
        "global_key = \"mexico_city\"\n",
        "\n",
        "tile_layer = lb_types.TileLayer(\n",
        "    url=\"https://s3-us-west-1.amazonaws.com/lb-tiler-layers/mexico_city/{z}/{x}/{y}.png\"\n",
        ")\n",
        "\n",
        "tiled_image_data = lb_types.TiledImageData(tile_layer=tile_layer,\n",
        "                                  tile_bounds=bounds,\n",
        "                                  zoom_levels=[17, 23])\n",
        "\n",
        "asset = {\n",
        "    \"row_data\": tiled_image_data.asdict(),\n",
        "    \"global_key\": global_key,\n",
        "    \"media_type\": \"TMS_GEO\"\n",
        "}\n",
        "\n",
        "dataset = client.create_dataset(name=\"geo_demo_dataset\")\n",
        "task= dataset.create_data_rows([asset])\n",
        "print(\"Errors:\",task.errors)\n",
        "print(\"Failed data rows:\", task.failed_data_rows)"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "## Step 2: Create/select an Ontology for your model predictions\n",
        "Your project should have the correct ontology setup with all the tools and classifications supported for your annotations, and the tool names and classification instructions should match the name/instructions fields in your annotations to ensure the correct feature schemas are matched.\n"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "ontology_builder = lb.OntologyBuilder(\n",
        "    tools=[\n",
        "        lb.Tool(tool=lb.Tool.Type.POINT, name=\"point_geo\"),\n",
        "        lb.Tool(tool=lb.Tool.Type.LINE, name=\"polyline_geo\"),\n",
        "        lb.Tool(tool=lb.Tool.Type.POLYGON, name=\"polygon_geo\"),\n",
        "        lb.Tool(tool=lb.Tool.Type.POLYGON, name=\"polygon_geo_2\"),\n",
        "        lb.Tool(tool=lb.Tool.Type.BBOX, name=\"bbox_geo\"), \n",
        "        lb.Tool( \n",
        "          tool=lb.Tool.Type.BBOX, \n",
        "          name=\"bbox_checklist_geo\",\n",
        "          classifications=[\n",
        "                lb.Classification(\n",
        "                    class_type=lb.Classification.Type.CHECKLIST,\n",
        "                    name=\"checklist_class_name\",\n",
        "                    options=[\n",
        "                      lb.Option(value=\"first_checklist_answer\")\n",
        "                    ]\n",
        "                ),\n",
        "            ]\n",
        "          ),\n",
        "        lb.Tool( \n",
        "          tool=lb.Tool.Type.BBOX, \n",
        "          name=\"bbox_text_geo\",\n",
        "          classifications=[\n",
        "                lb.Classification(\n",
        "                    class_type=lb.Classification.Type.TEXT,\n",
        "                    name=\"free_text_geo\"\n",
        "                ),\n",
        "            ]\n",
        "          )    \n",
        "      ],\n",
        "      classifications = [\n",
        "          lb.Classification(\n",
        "              class_type=lb.Classification.Type.CHECKLIST, \n",
        "              name=\"checklist_question_geo\",\n",
        "              options=[\n",
        "                  lb.Option(value=\"first_checklist_answer\"),\n",
        "                  lb.Option(value=\"second_checklist_answer\"), \n",
        "                  lb.Option(value=\"third_checklist_answer\")\n",
        "              ]\n",
        "          ), \n",
        "          lb.Classification(\n",
        "              class_type=lb.Classification.Type.RADIO, \n",
        "              name=\"radio_question_geo\",\n",
        "              options=[\n",
        "                  lb.Option(value=\"first_radio_answer\")\n",
        "              ]\n",
        "          ),\n",
        "          \n",
        "        lb.Classification( \n",
        "          class_type=lb.Classification.Type.RADIO, \n",
        "          name=\"nested_radio_question\", \n",
        "          options=[\n",
        "            lb.Option(value=\"first_radio_answer\",\n",
        "              options=[\n",
        "                  lb.Classification(\n",
        "                    class_type=lb.Classification.Type.RADIO,\n",
        "                    name=\"sub_radio_question\",\n",
        "                    options=[\n",
        "                      lb.Option(value=\"first_sub_radio_answer\")\n",
        "                    ]\n",
        "                ),\n",
        "              ]\n",
        "            ),\n",
        "          ], \n",
        "        ),\n",
        "        lb.Classification(\n",
        "          class_type=lb.Classification.Type.CHECKLIST,\n",
        "          name=\"nested_checklist_question\",\n",
        "          options=[\n",
        "              lb.Option(\"first_checklist_answer\",\n",
        "                options=[\n",
        "                  lb.Classification(\n",
        "                      class_type=lb.Classification.Type.CHECKLIST,\n",
        "                      name=\"sub_checklist_question\", \n",
        "                      options=[lb.Option(\"first_sub_checklist_answer\")]\n",
        "                  )\n",
        "              ]\n",
        "            )\n",
        "          ]\n",
        "      ) \n",
        "    ]\n",
        ")\n",
        "\n",
        "ontology = client.create_ontology(\"Ontology Geospatial Annotations\", ontology_builder.asdict(), media_type=lb.MediaType.Geospatial_Tile)"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "## Step 3: Create a Model and Model Run"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "# create Model\n",
        "model = client.create_model(name=\"geospatial_model_run_\" + str(uuid.uuid4()), \n",
        "                            ontology_id=ontology.uid)\n",
        "# create Model Run\n",
        "model_run = model.create_model_run(\"iteration 1\")"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "## Step 4: Send data rows to the Model Run"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "model_run.upsert_data_rows(global_keys=[global_key])"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "## Step 5. Create the predictions payload\n",
        "\n",
        "Create the annotations payload using the snippets in the **Supported Predictions Section**. \n",
        "\n",
        "The resulting label_ndjson should have exactly the same content for annotations that are supported by both"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        " ## Lets create another polygon annotation with python annotation tools that draws the image using cv2 and PIL python libraries\n",
        "\n",
        "hsv = cv2.cvtColor(tiled_image_data.value, cv2.COLOR_RGB2HSV)\n",
        "mask = cv2.inRange(hsv, (25, 50, 25), (100, 150, 255))\n",
        "kernel = np.ones((15, 20), np.uint8)\n",
        "mask = cv2.erode(mask, kernel)\n",
        "mask = cv2.dilate(mask, kernel)\n",
        "mask_annotation = lb_types.MaskData.from_2D_arr(mask)\n",
        "mask_data = lb_types.Mask(mask=mask_annotation, color=[255, 255, 255])\n",
        "h, w, _ = tiled_image_data.value.shape\n",
        "pixel_bounds = lb_types.TiledBounds(epsg=lb_types.EPSG.SIMPLEPIXEL,\n",
        "                          bounds=[lb_types.Point(x=0, y=0),\n",
        "                                  lb_types.Point(x=w, y=h)])\n",
        "transformer = lb_types.EPSGTransformer.create_pixel_to_geo_transformer(\n",
        "    src_epsg=pixel_bounds.epsg,\n",
        "    pixel_bounds=pixel_bounds,\n",
        "    geo_bounds=tiled_image_data.tile_bounds,\n",
        "    zoom=23)\n",
        "pixel_polygons = mask_data.shapely.simplify(3)\n",
        "list_of_polygons = [transformer(lb_types.Polygon.from_shapely(p)) for p in pixel_polygons.geoms]\n",
        "polygon_prediction_two = lb_types.ObjectAnnotation(value=list_of_polygons[0], name=\"polygon_geo_2\", confidence=0.5)\n"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "labels =[]\n",
        "labels.append(\n",
        "    lb_types.Label(\n",
        "        data=lb_types.TiledImageData(\n",
        "            global_key=global_key,\n",
        "            tile_layer=tile_layer,\n",
        "            tile_bounds=bounds,\n",
        "            zoom_levels=[12, 20]\n",
        "        ),\n",
        "        annotations = [\n",
        "            point_prediction,\n",
        "            polyline_prediction,\n",
        "            polygon_prediction,\n",
        "            bbox_prediction,\n",
        "            radio_prediction,\n",
        "            bbox_with_checklist_subclass,  \n",
        "            bbox_with_free_text_subclass,\n",
        "            checklist_prediction,\n",
        "            polygon_prediction_two, \n",
        "            nested_checklist_prediction, \n",
        "            nested_radio_prediction\n",
        "        ]\n",
        "    )\n",
        ")"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "# If using NDJSON"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "label_ndjson = []\n",
        "for prediction in [\n",
        "    radio_prediction_ndjson,\n",
        "    checklist_prediction_ndjson,\n",
        "    bbox_with_free_text_subclass_ndjson, \n",
        "    bbox_with_checklist_subclass_ndjson,\n",
        "    bbox_prediction_ndjson,\n",
        "    point_prediction_ndjson,\n",
        "    polyline_prediction_ndjson, \n",
        "    polygon_prediction_ndjson,\n",
        "    nested_checklist_prediction_ndjson, \n",
        "    nested_radio_prediction_ndjson\n",
        "]:\n",
        "  prediction.update({\n",
        "      'dataRow': {'globalKey': global_key},\n",
        "  })\n",
        "  label_ndjson.append(prediction)"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "## Step 6. Upload the predictions payload to the Model Run "
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "# Upload the prediction label to the Model Run\n",
        "upload_job_prediction = model_run.add_predictions(\n",
        "    name=\"prediction_upload_job\"+str(uuid.uuid4()),\n",
        "    predictions=labels)\n",
        "\n",
        "# Errors will appear for annotation uploads that failed.\n",
        "print(\"Errors:\", upload_job_prediction.errors)\n",
        "print(\"Status of uploads: \", upload_job_prediction.statuses)"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "## Step 7: Send annotations to the Model Run \n",
        "To send annotations to a Model Run, we must first import them into a project, create a label payload and then send them to the Model Run."
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "##### 7.1. Create a labelbox project"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "# Create a Labelbox project\n",
        "project = client.create_project(name=\"geospatial_prediction_demo\",                                    \n",
        "                                    media_type=lb.MediaType.Geospatial_Tile)\n",
        "project.setup_editor(ontology)"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "##### 7.2. Create a batch to send to the project "
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "project.create_batch(\n",
        "  \"batch_geospatial_prediction_demo\", # Each batch in a project must have a unique name\n",
        "  global_keys=[global_key], # A list of data rows or data row ids\n",
        "  priority=5 # priority between 1(Highest) - 5(lowest)\n",
        ")"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "##### 7.3 Create the annotations payload"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "####### Point #######\n",
        "\n",
        "# Python Annotation\n",
        "point_annotation = lb_types.ObjectAnnotation(\n",
        "  name = \"point_geo\",\n",
        "  value = lb_types.Point(x=-99.20647859573366, y=19.40018029091072),\n",
        ")\n",
        "\n",
        "####### Polyline #######\n",
        "line_points = []\n",
        "line_points_ndjson = []\n",
        "\n",
        "for sub in coords: \n",
        "  line_points.append(lb_types.Point(x=sub[0], y=sub[1]))\n",
        "  line_points_ndjson.append({\"x\":sub[0], \"y\":sub[1]})\n",
        "\n",
        "# Python Annotation \n",
        "polyline_annotation = lb_types.ObjectAnnotation(\n",
        "  name = \"polyline_geo\",\n",
        "  value = lb_types.Line(points=line_points),\n",
        ")\n",
        "\n",
        "\n",
        "\n",
        "polygon_points = []\n",
        "polygon_points_ndjson = []\n",
        "\n",
        "for sub in coords_polygon: \n",
        "  polygon_points.append(lb_types.Point(x=sub[0], y=sub[1]))\n",
        "  polygon_points_ndjson.append({\"x\":sub[0], \"y\":sub[1]})\n",
        "\n",
        "# Python Annotation \n",
        "polygon_annotation = lb_types.ObjectAnnotation(\n",
        "  name = \"polygon_geo\",\n",
        "  value = lb_types.Polygon(points=polygon_points),\n",
        ")\n",
        "\n",
        "\n",
        "\n",
        "bbox_top_left = lb_types.Point(x= -99.20746564865112, y=19.39799442829336)\n",
        "bbox_bottom_right = lb_types.Point(x=-99.20568466186523, y=19.39925939999194)\n",
        "\n",
        "# Python Annotation\n",
        "bbox_annotation = lb_types.ObjectAnnotation(\n",
        "  name = \"bbox_geo\",\n",
        "  value = lb_types.Rectangle(start=bbox_top_left, end=bbox_bottom_right)\n",
        ")\n",
        "\n",
        "# Python Annotation \n",
        "radio_annotation = lb_types.ClassificationAnnotation(\n",
        "    name=\"radio_question_geo\", \n",
        "    value=lb_types.Radio(answer=lb_types.ClassificationAnswer(name=\"first_radio_answer\"))\n",
        ")\n",
        "\n",
        "# Python Annotation\n",
        "bbox_with_checklist_subclass = lb_types.ObjectAnnotation(\n",
        "    name=\"bbox_checklist_geo\",\n",
        "    value=lb_types.Rectangle(\n",
        "        start=lb_types.Point(x=-99.210266, y=19.39540372195134), # Top left\n",
        "        end=lb_types.Point(x=-99.20621067903966, y=19.396901), # Bottom right\n",
        "    ),\n",
        "    classifications=[\n",
        "        lb_types.ClassificationAnnotation(\n",
        "            name=\"checklist_class_name\",\n",
        "            value=lb_types.Checklist(\n",
        "                answer=[lb_types.ClassificationAnswer(name=\"first_checklist_answer\")]\n",
        "            )\n",
        "        )\n",
        "    ]\n",
        ")\n",
        "\n",
        "bbox_with_free_text_subclass = lb_types.ObjectAnnotation(\n",
        "    name=\"bbox_text_geo\",\n",
        "    value=lb_types.Rectangle(\n",
        "        start=lb_types.Point(x=-99.21019613742828, y=19.397447957052933), # Top left\n",
        "        end=lb_types.Point(x=-99.20986354351044, y=19.39772119262215), # Bottom right\n",
        "    ),\n",
        "    classifications=[\n",
        "        lb_types.ClassificationAnnotation(\n",
        "            name=\"free_text_geo\",\n",
        "            value=lb_types.Text(answer=\"sample text\")\n",
        "        )\n",
        "    ]\n",
        ")\n",
        "\n",
        "checklist_annotation = lb_types.ClassificationAnnotation(\n",
        "    name=\"checklist_question_geo\",\n",
        "    value=lb_types.Checklist(answer = [\n",
        "        lb_types.ClassificationAnswer(name = \"first_checklist_answer\"),\n",
        "        lb_types.ClassificationAnswer(name = \"second_checklist_answer\"),\n",
        "        lb_types.ClassificationAnswer(name = \"third_checklist_answer\")\n",
        "    ])\n",
        "  )\n",
        "\n",
        "\n",
        "nested_radio_annotation = lb_types.ClassificationAnnotation(\n",
        "  name=\"nested_radio_question\",\n",
        "  value=lb_types.Radio(\n",
        "    answer=lb_types.ClassificationAnswer(\n",
        "      name=\"first_radio_answer\",\n",
        "      classifications=[\n",
        "        lb_types.ClassificationAnnotation(\n",
        "          name=\"sub_radio_question\",\n",
        "          value=lb_types.Radio(\n",
        "            answer=lb_types.ClassificationAnswer(\n",
        "              name=\"first_sub_radio_answer\"\n",
        "            )\n",
        "          )\n",
        "        )\n",
        "      ]\n",
        "    )\n",
        "  )\n",
        ")\n",
        "\n",
        "nested_checklist_annotation = lb_types.ClassificationAnnotation(\n",
        "  name=\"nested_checklist_question\",\n",
        "  value=lb_types.Checklist(\n",
        "    answer=[lb_types.ClassificationAnswer(\n",
        "      name=\"first_checklist_answer\",\n",
        "      classifications=[\n",
        "        lb_types.ClassificationAnnotation(\n",
        "          name=\"sub_checklist_question\",\n",
        "          value=lb_types.Checklist(\n",
        "            answer=[lb_types.ClassificationAnswer(\n",
        "            name=\"first_sub_checklist_answer\"\n",
        "          )]\n",
        "        ))\n",
        "      ]\n",
        "    )]\n",
        "  )\n",
        ")"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "##### 7.4. Create the label object"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "labels =[]\n",
        "labels.append(\n",
        "    lb_types.Label(\n",
        "        data=lb_types.TiledImageData(\n",
        "            global_key=global_key,\n",
        "            tile_layer=tile_layer,\n",
        "            tile_bounds=bounds,\n",
        "            zoom_levels=[12, 20]\n",
        "        ),\n",
        "        annotations = [\n",
        "            point_annotation,\n",
        "            polyline_annotation,\n",
        "            polygon_annotation,\n",
        "            bbox_annotation,\n",
        "            radio_annotation,\n",
        "            bbox_with_checklist_subclass,  \n",
        "            bbox_with_free_text_subclass,\n",
        "            checklist_annotation,\n",
        "            nested_checklist_annotation, \n",
        "            nested_radio_annotation\n",
        "        ]\n",
        "    )\n",
        ")"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "##### 7.5. Upload annotations to the project using Label Import"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "upload_job_annotation = lb.LabelImport.create_from_objects(\n",
        "    client = client,\n",
        "    project_id = project.uid,\n",
        "    name=\"geospatial_annotations_import_\" + str(uuid.uuid4()),\n",
        "    labels=labels)\n",
        "\n",
        "upload_job_annotation.wait_until_done()\n",
        "# Errors will appear for annotation uploads that failed.\n",
        "print(\"Errors:\", upload_job_annotation.errors)\n",
        "print(\"Status of uploads: \", upload_job_annotation.statuses)"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "##### 7.6. Send the annotations to the Model Run"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "# get the labels id from the project\n",
        "model_run.upsert_labels(project_id=project.uid)"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {},
      "source": [
        "## Optional deletions for cleanup \n"
      ],
      "cell_type": "markdown"
    },
    {
      "metadata": {},
      "source": [
        "#upload_job\n",
        "# project.delete()\n",
        "# dataset.delete()"
      ],
      "cell_type": "code",
      "outputs": [],
      "execution_count": null
    }
  ]
}